<template>
  <div class="ai-page">
    <van-nav-bar
      title="智能健康餐饮AI助手"
      :border="false"
      :safe-area-inset-top="true"
      class="custom-nav"
      left-arrow
      @click-left="goBack"
    />
    <div class="chat-container">
      <div v-for="(msg, idx) in messages" :key="idx" :class="['msg-row', msg.role]">
        <div class="avatar" v-if="msg.role === 'user'">
          <img :src="userAvatar" class="avatar-img" />
        </div>
        <div class="avatar" v-else>🤖</div>
        <div class="msg-bubble">
          <div v-if="msg.role === 'assistant'" class="ai-title">
            <van-icon name="calendar-o"/> 智能健康餐饮AI助手
          </div>
          <div class="msg-content">
            <div v-if="msg.image" class="msg-image-container">
              <img :src="msg.image" class="msg-img" />
            </div>  
            <div v-if="msg.content" v-html="renderMarkdown(msg.content)"></div>
            <div v-if="msg.loading" class="loading-dots">
              <span></span>
              <span></span>
              <span></span>
            </div>
          </div>
          <van-icon
            v-if="msg.role === 'assistant'"
            name="copy-o"
            class="copy-btn"
            @click="copyText(msg.content)"
          />
        </div>
      </div>
    </div>
    <div class="input-bar">
      <!-- 图片预览 -->
      <div v-if="imagePreview" class="img-preview">
        <img :src="imagePreview" />
        <van-icon name="clear" class="img-clear" @click="removeImage" />
      </div>
      <!-- 上传图片按钮 -->
      <van-uploader
        v-model="uploadedFiles"
        :max-count="1"
        :after-read="onFileChange"
        :preview-image="false"
        :disabled="!!imagePreview"
        class="custom-uploader"
        @click-upload="handleUploadClick"
      >
        <img src="../assets/images/add.png" class="img-upload-btn" :class="{ 'disabled': !!imagePreview }" />
      </van-uploader>
      <van-field
        v-model="input"
        placeholder="询问问题或发表任何内容..."
        @keyup.enter="send"
        :border="false"
        class="input"
      />
      <van-button type="primary" @click="send" :disabled="loading || (!input.trim() && !imagePreview)">发送</van-button>
    </div>
  </div>
</template>

<script setup>
import { ref, nextTick, onMounted } from 'vue'
import { showToast } from 'vant'
import { useRouter } from 'vue-router'
import MarkdownIt from 'markdown-it'
import { createChat, getMessageList } from '../api/ai-chat'
import { db, STORES } from '../utils/db'

const router = useRouter()
const goBack = () => router.back()
const API_KEY = "pat_GhkLNk1CvoxqqFpL7Xu4SF7cFSjZ3tFNe7qcj34dAVdNhqg9uVzezFcH4o18990J";
const BOT_ID = "7503096882806571043";
const USER_ID = "2";

let conversationId = null;
let additionalMessages = [];

const input = ref('')
const loading = ref(false)
const messages = ref([
  { role: 'assistant', content: '您好，我是您的智能健康餐饮AI助手，有什么可以帮您？' }
])

// 图片相关
const uploadedFiles = ref([])
const imagePreview = ref('')

const DEFAULT_AVATAR = 'https://img.yzcdn.cn/vant/cat.jpeg'
const userAvatar = ref(DEFAULT_AVATAR)
const userName = ref('')

onMounted(async () => {
  if (localStorage.getItem('isLogin')) {
    try {
      const userEmail = localStorage.getItem('userEmail')
      if (userEmail) {
        const user = await db.get(STORES.USER_LIST, userEmail)
        if (user) {
          userName.value = user.username || '测试用户'
          userAvatar.value = user.avatar || DEFAULT_AVATAR
          return
        }
      }
      
      // 如果无法从数据库获取用户信息，使用本地存储的信息
      const storedUserName = localStorage.getItem('userName')
      userName.value = storedUserName || '测试用户'
    } catch (error) {
      console.error('获取用户信息失败:', error)
      showToast('获取用户信息失败')
    }
  } else {
    userName.value = '未登录用户'
    userAvatar.value = DEFAULT_AVATAR
  }
})

const onFileChange = async (file) => {
  if (!file) return;
  
  // 创建图片对象用于处理
  const img = new Image()
  img.src = URL.createObjectURL(file.file)
  
  // 等待图片加载完成
  await new Promise((resolve) => {
    img.onload = resolve
  })
  
  // 创建canvas用于裁剪
  const canvas = document.createElement('canvas')
  const ctx = canvas.getContext('2d')
  
  // 设置目标尺寸（保持1:1比例）
  const targetSize = 100 // 目标尺寸为100x100像素
  
  // 计算裁剪区域
  let sourceX = 0
  let sourceY = 0
  let sourceWidth = img.width
  let sourceHeight = img.height
  
  // 如果图片不是正方形，从中心裁剪
  if (img.width !== img.height) {
    const size = Math.min(img.width, img.height)
    sourceX = (img.width - size) / 2
    sourceY = (img.height - size) / 2
    sourceWidth = size
    sourceHeight = size
  }
  
  // 设置canvas尺寸
  canvas.width = targetSize
  canvas.height = targetSize
  
  // 在canvas上绘制裁剪后的图片
  ctx.drawImage(
    img,
    sourceX, sourceY, sourceWidth, sourceHeight, // 源图片裁剪区域
    0, 0, targetSize, targetSize // 目标区域
  )
  
  // 将canvas转换为blob
  const blob = await new Promise(resolve => {
    canvas.toBlob(resolve, 'image/jpeg', 0.9)
  })
  
  // 创建新的File对象
  const croppedFile = new File([blob], file.file.name, {
    type: 'image/jpeg',
    lastModified: Date.now()
  })
  
  // 更新预览图
  imagePreview.value = URL.createObjectURL(blob)
  
  // 创建FormData并上传
  const formData = new FormData()
  formData.append("file", croppedFile)

  try {
    const res = await fetch("https://api.coze.cn/v1/files/upload", {
      method: "POST",
      headers: {
        'Authorization': `Bearer ${API_KEY}`,
        'Accept': 'application/json'
      },
      body: formData
    })

    const data = await res.json()
    console.log('Upload Response:', data)

    if (data.code !== 0) {
      throw new Error(data.msg || '文件上传失败')
    }

    const fileId = data?.data?.id
    if (!fileId) throw new Error("文件上传失败")
    
    // 保存文件ID
    file.fileId = fileId
    // 更新uploadedFiles，保持数组长度为1
    uploadedFiles.value = [file]
  } catch (error) {
    console.error('Upload Error:', error)
    showToast(error.message || '图片上传失败，请重试')
    removeImage()
  }
}

const removeImage = () => {
  imagePreview.value = ''
  uploadedFiles.value = []
}

// 滚动到底部
const scrollToBottom = () => {
  nextTick(() => {
    const el = document.querySelector('.chat-container')
    if (el) el.scrollTop = el.scrollHeight
  })
}

// 修改请求头配置
const headers = {
  'Authorization': `Bearer ${API_KEY}`,
  'Content-Type': 'application/json',
  'Accept': 'application/json'
}

// 修改图片上传的请求头
const uploadHeaders = {
  'Authorization': `Bearer ${API_KEY}`,
  'Accept': 'application/json'
}

// 修改发送消息函数
const send = async () => {
  if (!input.value.trim() && !imagePreview.value) return
  
  const userMsg = {
    role: 'user',
    content: input.value,
    image: imagePreview.value || null
  }
  messages.value.push(userMsg)
  
  // 添加一个带有加载状态的AI消息
  const loadingMsg = {
    role: 'assistant',
    content: '',
    loading: true
  }
  messages.value.push(loadingMsg)
  
  loading.value = true
  
  // 准备发送给 Coze 的消息
  const messageContent = imagePreview.value 
    ? JSON.stringify([
        { type: "text", text: input.value || "这张图中有什么？" },
        { type: "image", file_id: uploadedFiles.value[0]?.fileId }
      ])
    : input.value

  additionalMessages.push({
    content: messageContent,
    content_type: imagePreview.value ? "object_string" : "text",
    role: "user",
    type: "question"
  })

  input.value = ''
  imagePreview.value = ''
  uploadedFiles.value = [] // 清空上传文件列表
  scrollToBottom()

  try {
    // 创建对话
    const createData = await createChat(additionalMessages)

    if (createData.code !== 0) {
      throw new Error(createData.msg || '创建对话失败')
    }

    const { conversation_id, id: chat_id } = createData.data
    conversationId = conversation_id

    // 等待AI回复，轮询直到拿到type为answer的消息或超时
    let answerMsg = null
    let retries = 150 // 最多等待150次，每次1.5秒，约3分钟
    while (retries-- > 0 && !answerMsg) {
      await new Promise(resolve => setTimeout(resolve, 1500))
      const msgData = await getMessageList(conversation_id, chat_id)

      if (msgData.code !== 0) {
        throw new Error(msgData.msg || '获取消息失败')
      }
      if (!Array.isArray(msgData?.data)) continue

      // 查找 type 为 answer 的 assistant 消息
      answerMsg = msgData.data.find(
        m => m.role === "assistant" && m.type === "answer" && m.content && typeof m.content === "string"
      )
    }

    if (!answerMsg) {
      // 移除加载消息并添加错误消息
      messages.value.pop()
      messages.value.push({ role: 'assistant', content: '❌ 未获取到回复内容。' })
    } else {
      // 移除加载消息并添加实际回复
      messages.value.pop()
      messages.value.push({
        role: 'assistant',
        content: answerMsg.content
      })
      additionalMessages.push({
        content_type: "text",
        content: answerMsg.content,
        role: "assistant",
        type: answerMsg.type
      })
    }
  } catch (err) {
    // 移除加载消息并添加错误消息
    messages.value.pop()
    messages.value.push({ role: 'assistant', content: `❌ ${err.message || '请求失败，请稍后再试。'}` })
  } finally {
    loading.value = false
    scrollToBottom()
  }
}

// 复制AI回复
const copyText = (text) => {
  navigator.clipboard.writeText(text)
  showToast('已复制')
}

const md = new MarkdownIt()
const renderMarkdown = (text) => md.render(text || '')

// 处理上传按钮点击
const handleUploadClick = () => {
  if (imagePreview.value) {
    showToast('最多只能上传一张图片')
  }
}
</script>

<style scoped>
.ai-page {
  display: flex;
  flex-direction: column;
  height: 100vh;
  background: linear-gradient(135deg, #e9eafc 0%, #e6e6fa 100%);
}

.custom-nav {
  background: transparent !important;
}

.custom-nav :deep(.van-nav-bar__title) {
  color: #333;
  font-size: 17px;
  font-weight: 600;
}

.custom-nav :deep(.van-nav-bar__arrow) {
  color: #333;
  font-size: 18px;
}

.chat-container {
  flex: 1;
  overflow-y: auto;
  padding: 16px 12px 80px 12px;
}

.msg-row {
  display: flex;
  align-items: flex-start;
  margin-bottom: 18px;
}

.msg-row.user {
  flex-direction: row-reverse;
}

.avatar {
  width: 40px;
  height: 40px;
  background: #fff;
  border-radius: 50%;
  color: #7c5dfa;
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: bold;
  margin: 0 8px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
  overflow: hidden;
}

.avatar-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.msg-bubble {
  max-width: 70vw;
  background: #fff;
  border-radius: 16px;
  padding: 12px 16px;
  box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08);
  position: relative;
  word-break: break-all;
}

.msg-row.user .msg-bubble {
  background: linear-gradient(135deg, #7c5dfa 0%, #a48fff 100%);
  color: #fff;
}

.ai-title {
  font-size: 13px;
  color: #7c5dfa;
  margin-bottom: 4px;
  display: flex;
  align-items: center;
  gap: 4px;
}

.copy-btn {
  position: absolute;
  right: 8px;
  bottom: 8px;
  font-size: 18px;
  color: #b0b0b0;
  cursor: pointer;
  transition: all 0.3s ease;
}

.copy-btn:hover {
  color: #7c5dfa;
  transform: scale(1.1);
}

.input-bar {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  background: #fff;
  display: flex;
  align-items: center;
  padding: 12px 16px;
  box-shadow: 0 -2px 12px rgba(0, 0, 0, 0.08);
  z-index: 10;
}

.custom-uploader {
  margin-right: 8px;
}

.custom-uploader :deep(.van-uploader__wrapper) {
  display: flex;
  align-items: center;
}

.custom-uploader :deep(.van-uploader__input-wrapper) {
  width: 24px;
  height: 24px;
  margin: 0;
  padding: 0;
}

.img-upload-btn {
  width: 24px;
  height: 24px;
  cursor: pointer;
  transition: transform 0.3s ease;
}

.img-upload-btn.disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

.img-upload-btn:not(.disabled):hover {
  transform: scale(1.1);
}

.img-preview {
  position: absolute;
  left: 48px;
  bottom: 60px;
  background: #fff;
  border-radius: 12px;
  box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
  padding: 4px;
  display: flex;
  align-items: center;
  z-index: 20;
}

.img-preview img {
  width: 48px;
  height: 48px;
  object-fit: cover;
  border-radius: 8px;
}

.img-clear {
  font-size: 18px;
  color: #f56c6c;
  margin-left: 4px;
  cursor: pointer;
  transition: transform 0.3s ease;
}

.img-clear:hover {
  transform: scale(1.1);
}

.input {
  flex: 1;
  margin-right: 12px;
  background: #f5f6fa;
  border-radius: 12px;
  padding: 8px 12px;
}

.msg-image-container {
  margin-bottom: 8px;
}

.msg-img {
  max-width: 200px;
  max-height: 200px;
  border-radius: 12px;
  object-fit: cover;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}

.loading-dots {
  display: flex;
  align-items: center;
  gap: 4px;
  padding: 8px 0;
}

.loading-dots span {
  width: 8px;
  height: 8px;
  background: #7c5dfa;
  border-radius: 50%;
  display: inline-block;
  animation: bounce 1.4s infinite ease-in-out both;
}

.loading-dots span:nth-child(1) {
  animation-delay: -0.32s;
}

.loading-dots span:nth-child(2) {
  animation-delay: -0.16s;
}

@keyframes bounce {
  0%, 80%, 100% { 
    transform: scale(0);
  } 
  40% { 
    transform: scale(1.0);
  }
}
</style>